package com.wildeman.tokati.db;


import java.util.ArrayList;
import java.util.List;

import com.wildeman.tokati.core.Grupo;
import com.wildeman.tokati.core.Miembro;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;


public class DataHelper 
{
	private static final String DATABASE_NAME = "tokati.db";
	private static final int DATABASE_VERSION = 2;
	
	private static final String TABLA_MIEMBROS = "MIEMBROS";
	private static final String TABLA_GRUPOS = "GRUPOS";
	private static final String TABLA_GRUPO_MIEMBRO = "GRUPO_MIEMBROS";
	private static final String TABLA_SECUENCIA = "sqlite_sequence";
	
	private static final String TAG = "BBDD";
	
	private Context context;
	private SQLiteDatabase db;
	
	OpenHelper openHelper;
	
	public DataHelper(Context context) 
	{
		this.context = context;
		
		openHelper = new OpenHelper(this.context);
		
		this.db = openHelper.getWritableDatabase();
	}
	
	public void cerrar()
	{
		Log.d(TAG, "Cerrando la BBDD...");
		if (openHelper != null) 
		{
	        openHelper.close();
	    }
		Log.d(TAG, "BBDD Cerrada!");
	}
	
	
	
	
	/**
	 * Inserta un nuevo registro en la tabla de grupos
	 * @param nombreGrupo
	 * @return
	 */
	public int insertarGrupo(Grupo grupo)
	{
		String insertGrupo = "INSERT INTO "+ TABLA_GRUPOS +" (ES_FAVORITO, NOM_GRUPO) VALUES (?,?)";

		SQLiteStatement insertUpdateStmt;
		
		//Inserta
		insertUpdateStmt = this.db.compileStatement(insertGrupo);
			
		insertUpdateStmt.bindLong(1, grupo.isFavorito()==true?1:0);
		insertUpdateStmt.bindString(2, grupo.getNombreGrupo());
			
		Log.d(TAG, "Preparando insert de nuevoGrupo: " + grupo.toString());
		insertUpdateStmt.executeInsert();
		Log.d(TAG, "Registro insertado");
		
		return devuelveUltimoIdTabla(TABLA_GRUPOS);
		
	}
	
	
	public void actualizaGrupo(Grupo grupo)
	{
		String updateGrupo = "UPDATE " + TABLA_GRUPOS + " SET ES_FAVORITO = ?, NOM_GRUPO = ? WHERE ID_GRUPO = ?";
		SQLiteStatement insertUpdateStmt;
		
		//Actualiza
		insertUpdateStmt = this.db.compileStatement(updateGrupo);
		insertUpdateStmt.bindLong(1, grupo.isFavorito()==true?1:0);
		insertUpdateStmt.bindString(2, grupo.getNombreGrupo());
		insertUpdateStmt.bindLong(3, grupo.getIdGrupo());
		
		Log.d(TAG, "Preparando update del grupo: " + grupo.toString());
		insertUpdateStmt.execute();
		Log.d(TAG, "Registro Actualizado");
	}
	
	
	public void actualizaMiembro (Miembro miembro)
	{
		String updateMiembro = "UPDATE " + TABLA_MIEMBROS + " SET GENERO = ?, IMAGEN = ?, NOM_MIEMBRO = ? WHERE ID_MIEMBROS = ?";
		SQLiteStatement insertUpdateStmt; 
		
		//Actualiza
		insertUpdateStmt = this.db.compileStatement(updateMiembro);
		insertUpdateStmt.bindLong(1, miembro.getGenero());
		insertUpdateStmt.bindString(2, miembro.getImagen());
		insertUpdateStmt.bindString(3, miembro.getNombres());
		insertUpdateStmt.bindLong(4, miembro.getIdMiembro());
		
		Log.d(TAG, "Preparando update del grupo: " + miembro.toString());
		insertUpdateStmt.execute();
		Log.d(TAG, "Registro Actualizado");
		
	}
	
	
	/**
	 * Elimina el grupo y todos sus miembros
	 * @param id_grupo
	 */
	public void eliminarGrupo(int id_grupo)
	{
		String deleteGrupoMiembros = "DELETE FROM "+TABLA_GRUPO_MIEMBRO+" WHERE ID_GRUPO = ?";
		String deleteGrupo = "DELETE FROM "+ TABLA_GRUPOS +" WHERE ID_GRUPO = ?";
		
		SQLiteStatement deleteStmt;
		deleteStmt = this.db.compileStatement(deleteGrupoMiembros);
		
		deleteStmt.bindLong(1, id_grupo);
		
		Log.d(TAG, "Preparando delete de todos los miembros del grupo: " + id_grupo);
		deleteStmt.execute();
		Log.d(TAG, "Registros eliminados");
		
		deleteStmt = this.db.compileStatement(deleteGrupo);
		deleteStmt.bindLong(1, id_grupo);
		
		
		Log.d(TAG, "Preparando delete del grupo: " + id_grupo);
		deleteStmt.execute();
		Log.d(TAG, "Registros eliminados. Salimos");
		
	}
	
	
	public void marcaGrupoFavorito(int id_grupo, boolean nuevo_valor)
	{
		String updateGrupo = "UPDATE "+ TABLA_GRUPOS +" SET ES_FAVORITO = ? WHERE ID_GRUPO = ?";
		
		SQLiteStatement updateStmt;
		updateStmt = this.db.compileStatement(updateGrupo);
		
		updateStmt.bindLong(1, nuevo_valor==true?1:0);
		updateStmt.bindLong(2, id_grupo);
		
		Log.d(TAG, "Preparando update del grupo: " + id_grupo);
		updateStmt.execute();
		Log.d(TAG, "Registros actualizados");
	}
	
	
	
	/**
	 * Inserta un nuevo registro en la tabla MIEMBROS
	 * @param nombreMiembro
	 * @param rutaImagen
	 * @param genero
	 * @return
	 */
	public long insertarMiembro(String nombreMiembro, String rutaImagen, int genero)
	{
		return insertarMiembro(nombreMiembro, rutaImagen, genero, -1);
	}
	
	
	/**
	 * Inserta un nuevo registro en la tabla MIEMBROS
	 * @param nombreMiembro
	 * @param rutaImagen
	 * @param genero
	 * @param id_grupo
	 * @return devuelve el nuevo identificador del registro
	 */
	public int insertarMiembro(String nombreMiembro, String rutaImagen, int genero, int id_grupo)
	{
		String insertMiembro = "INSERT INTO "+TABLA_MIEMBROS+" (GENERO, IMAGEN, NOM_MIEMBRO) VALUES (?,?,?)";
		SQLiteStatement insertStmt;
		insertStmt = this.db.compileStatement(insertMiembro);
		
		insertStmt.bindLong(1, genero);
		insertStmt.bindString(2, rutaImagen==null?"":rutaImagen);
		insertStmt.bindString(3, nombreMiembro);
		
		Log.d(TAG, "Preparando insert de nuevoMiembro: " + nombreMiembro + ", " + rutaImagen + ", " + genero + ", " + id_grupo);
		
		insertStmt.executeInsert();
		
		Log.d(TAG, "Registro insertado");
		
		int nuevoIdMiembro = devuelveUltimoIdTabla(TABLA_MIEMBROS); 
		
		asociaMiembroEnGrupo(id_grupo, nuevoIdMiembro);
		
		return nuevoIdMiembro;
	}
	
	
	/**
	 * Inserta una nueva asociación entre un miembro y su grupo
	 * @param idGrupo
	 * @param idMiembro
	 */
	private void asociaMiembroEnGrupo(int idGrupo, int idMiembro)
	{
		String insertGrupoMiembro = "INSERT INTO "+TABLA_GRUPO_MIEMBRO+" (ID_GRUPO, ID_MIEMBRO) VALUES (?,?)";
		SQLiteStatement insertStmt;
		insertStmt = this.db.compileStatement(insertGrupoMiembro);
		
		insertStmt.bindLong(1, idGrupo);
		insertStmt.bindLong(2, idMiembro);
		
		Log.d(TAG, "Preparando insert de miembro en grupo: " + idGrupo + ", " + idMiembro );
		
		insertStmt.executeInsert();
		
		Log.d(TAG, "Registro insertado");
	}
	
	
	
	
	/**
	 * Devuelve el último id de una tabla siempre y cuando el identificador sea una secuencia.
	 * @param nombreTabla
	 * @return
	 */
	private int devuelveUltimoIdTabla(String nombreTabla)
	{
		int ultimoId = -1;
		
		Log.d(TAG, "Ejecutando query...");
		
		Cursor cursor = this.db.rawQuery("SELECT seq FROM " + TABLA_SECUENCIA + " WHERE name = ?",new String[] {nombreTabla});
		//Cursor cursor = this.db.query(TABLA_SECUENCIA, new String[] { "seq" }, "name", new String[] {nombreTabla}, null, null, null);
		
		Log.d(TAG, "Query lanzada. Procesando resultados");
		if (cursor.moveToFirst()) 
	    {
			
	         do 
	         {
	            ultimoId = cursor.getInt(0);
	         } 
	         while (cursor.moveToNext());
	    }
	
	    if (cursor != null && !cursor.isClosed()) 
	    {
	    	Log.d(TAG,"Cerrando cursor..."); 
	    	cursor.close();
	    	Log.d(TAG,"Cursor Cerrado");
	    }
	    
	    Log.d(TAG, "Procesado. ultimoId:" + ultimoId);
		
		return ultimoId;
	}
	

	/**
	 * Devuelve un objeto List con los grupos almacenados en BBDD
	 * @return
	 */
	public List<Grupo> listarGrupos()
	{
		Grupo grupo = null;
		List<Grupo> list = new ArrayList<Grupo>();
		
		Log.d(TAG,"Consultando lista de grupos en BBDD");
		
		Cursor cursor = this.db.rawQuery("SELECT ID_GRUPO, NOM_GRUPO, ES_FAVORITO FROM " + TABLA_GRUPOS, new String[]{});
		
		Log.d(TAG,"Procesando resultados..");
	    if (cursor.moveToFirst()) 
	    {
	         do 
	         {
	        	grupo = new Grupo(cursor.getInt(0), cursor.getString(1), cursor.getInt(2)==0?false:true); 
	        	list.add(grupo);
	        	Log.d(TAG, grupo.toString());
	        	
	         } 
	         while (cursor.moveToNext());
	    }
	
	    if (cursor != null && !cursor.isClosed()) 
	    {
	    	Log.d(TAG,"Cerrando cursor..."); 
	    	cursor.close();
	    	Log.d(TAG,"Cursor Cerrado");
	    }
	    
	    Log.d(TAG,"Registros totales procesados:" + list.size());
	    
		return list;
	}

	
	/**
	 * Devuelve un objeto List con los grupos almacenados en BBDD y marcados como favortos
	 * @return
	 */
	public List<Grupo> listarGruposFavoritos()
	{
		Grupo grupo = null;
		List<Grupo> list = new ArrayList<Grupo>();
		
		Log.d(TAG,"Consultando lista de grupos favoritos en BBDD");
		
		Cursor cursor = this.db.rawQuery("SELECT ID_GRUPO, NOM_GRUPO, ES_FAVORITO FROM " + TABLA_GRUPOS + " WHERE ES_FAVORITO <> 0", new String[]{});
		
		Log.d(TAG,"Procesando resultados..");
	    if (cursor.moveToFirst()) 
	    {
	         do 
	         {
	        	grupo = new Grupo(cursor.getInt(0), cursor.getString(1), cursor.getInt(2)==0?false:true); 
	        	list.add(grupo);
	        	Log.d(TAG, grupo.toString());
	        	
	         } 
	         while (cursor.moveToNext());
	    }
	
	    if (cursor != null && !cursor.isClosed()) 
	    {
	    	Log.d(TAG,"Cerrando cursor..."); 
	    	cursor.close();
	    	Log.d(TAG,"Cursor Cerrado");
	    }
	    
	    Log.d(TAG,"Registros totales procesados:" + list.size());
	    
		return list;
	}	
	
	
	public Grupo detalleGrupo(int id_grupo)
	{
		Grupo elGrupo = null;
		
		//Cursor cursor = this.db.rawQuery("select ID_MIEMBROS, GENERO, IMAGEN, NOM_MIEMBRO from "+TABLA_MIEMBROS+", "+TABLA_GRUPO_MIEMBRO+" where miembros.id_miembros = grupo_miembros.id_miembro and grupo_miembros.id_grupo = ?",new String[] {String.valueOf(idGrupo)});
		
		
		return elGrupo;
	}
	
	
	
	

	/**
	 * Devuelve una lista de los miembros de un grupo
	 * @param idGrupo identificador del grupo
	 * @return
	 */
	public List<Miembro> listarMiembrosGrupo(int idGrupo) 
	{
		Miembro miembro = null;
		
		Log.d(TAG,"Consultando lista miembros del grupo: " + idGrupo);
		
		List<Miembro> list = new ArrayList<Miembro>();
		Cursor cursor = this.db.rawQuery("select ID_MIEMBROS, GENERO, IMAGEN, NOM_MIEMBRO from "+TABLA_MIEMBROS+", "+TABLA_GRUPO_MIEMBRO+" where miembros.id_miembros = grupo_miembros.id_miembro and grupo_miembros.id_grupo = ?",new String[] {String.valueOf(idGrupo)});

	
		Log.d(TAG,"Procesando resultados..");
	    if (cursor.moveToFirst()) 
	    {
	         do 
	         {
	            miembro = new Miembro(cursor.getInt(0), cursor.getString(3), cursor.getString(2), cursor.getInt(1));
	        	list.add(miembro);
	         } 
	         while (cursor.moveToNext());
	    }
	
	    if (cursor != null && !cursor.isClosed()) 
	    {
	    	Log.d(TAG,"Cerrando cursor..."); 
	    	cursor.close();
	    	Log.d(TAG,"Cursor Cerrado");
	    }
	    
	    Log.d(TAG,"Registros totales procesados:" + list.size());
	    
	    return list;
	 }
	
	
/*
	public void deleteAll() 
	{
		Log.d(TAG, "Borrando tabla...");
		this.db.delete(TABLE_NAME, null, null);
		
		Log.d(TAG, "tabla " + TABLE_NAME + " borrada!");
	}
	
*/	 

	private static class OpenHelper extends SQLiteOpenHelper 
	{
	      OpenHelper(Context context) 
	      {
	         super(context, DATABASE_NAME, null, DATABASE_VERSION);
	      }

	      @Override
	      public void onCreate(SQLiteDatabase db) 
	      {
	         db.execSQL("CREATE TABLE "+TABLA_MIEMBROS+" (GENERO NUMERIC, ID_MIEMBROS INTEGER PRIMARY KEY AUTOINCREMENT, IMAGEN TEXT, NOM_MIEMBRO TEXT)");
	         db.execSQL("CREATE TABLE "+ TABLA_GRUPOS +" (ES_FAVORITO NUMERIC, ID_GRUPO INTEGER PRIMARY KEY AUTOINCREMENT, NOM_GRUPO TEXT)");
	         db.execSQL("CREATE TABLE GRUPO_MIEMBROS (ID_GRUPO NUMERIC, ID_MIEMBRO NUMERIC)");
	         db.execSQL("CREATE INDEX IDX01_MIEMBROS ON "+TABLA_MIEMBROS+"(NOM_MIEMBRO ASC)");
	         db.execSQL("CREATE INDEX IDX01_GRUPOS ON GRUPOS(NOM_GRUPO ASC)");
	      }

	      @Override
	      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
	      {
	         Log.w(TAG, "Upgrading database, this will drop tables and recreate.");
	         db.execSQL("DROP TABLE IF EXISTS GRUPO_MIEMBROS");
	         db.execSQL("DROP TABLE IF EXISTS "+ TABLA_GRUPOS );
	         db.execSQL("DROP TABLE IF EXISTS " + TABLA_MIEMBROS );
	         onCreate(db);
	      }
	}
}

